#include "OperationLevel.h"

#include <mxml.h>
#include <fat.h>

OperationLevel::OperationLevel()
{
//   bone = new ComplexSprite();
   collision_state = false;
   level_running   = false;
   grab_state      = false;
   level_won       = false;
}

OperationLevel::~OperationLevel()
{

}

void OperationLevel::EndLevel()
{
   collision_state = false;
   level_running   = false;
   grab_state      = false;
   level_won       = false;
}

void OperationLevel::Cleanup()
{
   wall_list.clear();
   EndLevel();
}

//return true on good level load
bool OperationLevel::LoadLevel(const char* level_config_file)
{
  FILE *fp;
  mxml_node_t *tree;
  mxml_node_t *level_n;
  mxml_node_t *bone_n;
  mxml_node_t *collisions_n;
  mxml_node_t *home_n;
  mxml_node_t *walls_n;
  mxml_node_t *wall_n;

  printf("Load Level (%s)\n", level_config_file);
  printf("Cleanup...\n");
  Cleanup();

  printf("Open FIle...\n");
  fp = fopen(level_config_file, "r");
  if(fp == NULL) return false;

  tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);
  fclose(fp);

  printf("Find level\n");
  level_n = mxmlFindElement(tree, tree, "level", NULL, NULL, MXML_DESCEND); 
  if(level_n == NULL) return false;
  printf("  parsing level\n");
  title = (char*)mxmlElementGetAttr(level_n,"title");
  description = (char*)mxmlElementGetAttr(level_n,"description");

  printf("Find bone\n");
  bone_n =  mxmlFindElement(level_n, level_n, "bone", NULL, NULL, MXML_DESCEND); 
  if(bone_n == NULL) return false;
  printf("  Parsing Bone\n");
  if(bone_img.LoadImage((char*)mxmlElementGetAttr(bone_n,"img_file")) != IMG_LOAD_ERROR_NONE) return false;

  printf("Done parsing bone...\n");
  bone.SetImage(&bone_img);
  bone_start_x  =  atof(mxmlElementGetAttr(bone_n,"x"));
  bone_start_y  =  atof(mxmlElementGetAttr(bone_n,"y"));
  bone_start_rotation  =  atof(mxmlElementGetAttr(bone_n,"rotation"))/2.0;
  bone.SetZoom(atof(mxmlElementGetAttr(bone_n,"zoom")));
  bone.SetPosition(bone_start_x, bone_start_y);
  bone.SetRotation(bone_start_rotation);

 /* printf("Add Bone Collisions..\n");
  bone->ClearCollisionBoxes();
    for(collisions_n = mxmlFindElement(bone_n, bone_n, "collision", NULL, NULL, MXML_DESCEND); 
        collisions_n != NULL; 
        collisions_n = mxmlFindElement(collisions_n, bone_n, "collision", NULL, NULL, MXML_DESCEND))
  {
     bone->AddCollisionBox(atof(mxmlElementGetAttr(collisions_n,"x")),
						   atof(mxmlElementGetAttr(collisions_n,"y")),
						   atof(mxmlElementGetAttr(collisions_n,"w")),
						   atof(mxmlElementGetAttr(collisions_n,"h")));
  }
  */
  printf("Find home.\n");
  home_n =  mxmlFindElement(level_n, level_n, "home", NULL, NULL, MXML_DESCEND); 
  if(home_n == NULL) return false;
  printf("   Parsing home\n");
  if(home_img.LoadImage((char*)mxmlElementGetAttr(home_n,"img_file")) != IMG_LOAD_ERROR_NONE) return false;
  home.SetImage(&home_img);
  home.SetPosition(atof(mxmlElementGetAttr(home_n,"x")), atof(mxmlElementGetAttr(home_n,"y"))); 
  home.SetRotation(atof(mxmlElementGetAttr(home_n,"rotation"))/2.0);
  home.SetZoom(atof(mxmlElementGetAttr(home_n, "zoom")));

  printf("Find Walls\n");
  walls_n = mxmlFindElement(level_n, level_n, "walls", NULL, NULL, MXML_DESCEND);
  if(walls_n == NULL) return false;
  if(wall_img.LoadImage((char*)mxmlElementGetAttr(walls_n, "img_file")) != IMG_LOAD_ERROR_NONE) return false;
/*
  printf("Add wall Collisions..\n");
  std::vector<Rectangle> tmpColVec;
    for(collisions_n = mxmlFindElement(walls_n, walls_n, "collision", NULL, NULL, MXML_DESCEND); 
        collisions_n != NULL; 
        collisions_n = mxmlFindElement(collisions_n, walls_n, "collision", NULL, NULL, MXML_DESCEND))
  {
	Rectangle r;
	r.x = atof(mxmlElementGetAttr(collisions_n,"x"));
	r.y = atof(mxmlElementGetAttr(collisions_n,"y"));
	r.width = atof(mxmlElementGetAttr(collisions_n,"w"));
	r.height = atof(mxmlElementGetAttr(collisions_n,"h"));
	tmpColVec.push_back(r);
  }
  */
  printf("Add Walls..\n");
  //Add All Walls
    for(wall_n = mxmlFindElement(walls_n, walls_n, "wall", NULL, NULL, MXML_DESCEND); 
        wall_n != NULL; 
        wall_n = mxmlFindElement(wall_n, walls_n, "wall", NULL, NULL, MXML_DESCEND))
  {
     Sprite* tWall = new Sprite();
     tWall->SetImage(&wall_img);
     tWall->SetZoom(atof(mxmlElementGetAttr(wall_n,"zoom")));    
     tWall->SetRotation(atof(mxmlElementGetAttr(wall_n,"rotation"))/2.0);
     tWall->SetPosition(atof(mxmlElementGetAttr(wall_n,"x")),atof(mxmlElementGetAttr(wall_n,"y")));

//	 for(int i = 0; i < tmpColVec.size(); i++)
//		tWall->AddCollisionBox(tmpColVec.at(i).x, tmpColVec.at(i).y, tmpColVec.at(i).width, tmpColVec.at(i).height);
     
	 wall_list.push_back(tWall);
  }
   printf("Done\n");

  return true;   
}

void OperationLevel::InitLevel(bool reset_bone)
{
   if(reset_bone)
   {
      bone.SetPosition(bone_start_x, bone_start_y);
      bone.SetRotation(bone_start_rotation);
   }
   collision_state = false;
   level_running   = false;
   grab_state      = false;
   level_won       = false;
}

void OperationLevel::Draw(f32 zoom_val)
{
   for(unsigned int i =0; i < wall_list.size(); i++)
   {
      wall_list.at(i)->Draw();
   }

   //home.SetZoom(zoom_val);
   home.Draw();

   //bone->SetZoom(zoom_val);
   bone.Draw();

}

//return true if bone is at level end;
bool OperationLevel::Update(Sprite* tweezer, bool isGrabbing)
{
   if(tweezer != NULL)
   {
	   collision_state = false;
	   
	   /*Check if tweezer grabs the plate (Pick up tweezers)*/
	   if(tweezer->CollidesWith(&home,true) && isGrabbing)
	   {
	      level_running = true;
	   }
	   
	   grab_state = false;

	   if(level_running)
	   {
	      /*Check if tweezer grabs bone */
	      if(bone.CollidesWith(tweezer,true) && isGrabbing)
	      {
		 grab_state = true;    
	      }

	      /* Check if bone makes it home! (WIN) */
	      if(!grab_state && bone.CollidesWith(&home,true))
	      {
		 level_won = true;    
		 return true;
	      }
	 
	      /* Check collision with walls */
	      for(unsigned int i = 0; i < wall_list.size(); i++)
	      {
			 if(wall_list.at(i)->CollidesWith(tweezer,true))
			 {
				collision_state = true;
				grab_state = false;
				return true;
			 }
			 
			 if(grab_state == true)
			 {
				if(bone.CollidesWith(wall_list.at(i),true))
				{
				   grab_state = false;
				   collision_state = true;
				   return true;
				}
			 }
	      }
	   }
   }
   else
   {
      printf("ERROR NULL TWEEZER!\n");
   }
   return false;
}

